if (!window.utils) window.utils = {}
var _utils = {
  noop: function () {},
  setBackUrl: function (url) {
    window.history.pushState(null, '', window.location.href)
    window.addEventListener('popstate', function () {
      window.location.href = url
    }, false)
  },
  isEmpty: function (obj) {
    if (obj === null) return true
    var type = Object.prototype.toString.call(obj)
    if (type === '[object Array]' || type === '[object String]') {
      return obj.length === 0
    }
    if (type === '[object Number]') {
      return obj === 0
    }
    for (var name in obj) {
      return false
    }
    return true
  },
  getQueryString: function (name) {
    var r1 = getMatched(name, window.location.search)
    if (r1) return r1
    var key = arguments[1]
    if (key) {
      return getMatched(name, window.localStorage.getItem(key))
    }
    return null

    function getMatched (name, string) {
      if (string) {
        var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
        var len = string.indexOf('?') == 0 ? 1 : 0
        var r = string.substr(len).match(reg)
        if (r != null) return unescape(r[2])
      }
      return null
    }
  },
  isWeChat: function () {
    return /(MicroMessenger)/i.test(navigator.userAgent)
  },
  isIOS: function () {
    return /iPad|iPhone|iPod/.test(navigator.platform)
  },
  isIosWebView: function () {
    return /iPad|iPhone|iPod/.test(navigator.platform) && navigator.userAgent.indexOf('Safari') === -1
  },
  isAndroid: function () {
    return /(android)/i.test(navigator.userAgent)
  },
  isAndroidWebView: function () {
    return /(android)/i.test(navigator.userAgent) && typeof android === 'object'
  },
  isWebView: function () {
    return utils.isIosWebView() || utils.isAndroidWebView()
  },
  isMobile: function () {
    return utils.isIOS() || utils.isAndroid()
  },
  parseUrlParam: function (key) {
    var match,
      pl = /\+/g, // Regex for replacing addition symbol with a space
      search = /([^&=]+)=?([^&]*)/g,
      decode = function (s) {
        return decodeURIComponent(s.replace(pl, ' '))
      },
      query = window.location.search.substring(1),
      params = {}
    while (match = search.exec(query))
      params[decode(match[1])] = decode(match[2])
    return key ? params[key] : params
  },
  parseUrlHash: function (key) {
    var match,
      pl = /\+/g, // Regex for replacing addition symbol with a space
      search = /([^&=]+)=?([^&]*)/g,
      decode = function (s) {
        return decodeURIComponent(s.replace(pl, ' '))
      },
      query = window.location.hash.substring(1),
      params = {}
    while (match = search.exec(query))
      params[decode(match[1])] = decode(match[2])
    return key ? params[key] : params
  },
  saveUrlParam: function () {
    var param = utils.getUrlParam()
    try {
      if (param) {
        var state = Math.random().toString().slice(-6)
        delete param.state
        delete param.code
        window.localStorage.setItem('param_' + state, JSON.stringify(param))
        console.log('save url param: ', param)
        return '&state=' + state
      }
    } catch (e) {}
    return ''
  },
  recoverUrlParam: function () {
    var state = utils.getUrlParam('state')
    try {
      var param = JSON.parse(window.localStorage.getItem('param_' + state))
      delete param.state
      delete param.code
      utils.setUrlParam(param)
      window.localStorage.removeItem('param_' + state)
      return param
    } catch (e) {}
  },
  getUrlParam: function (key) {
    return utils.parseUrlParam(key)
  },
  getUrlHash: function (key) {
    return utils.parseUrlHash(key)
  },
  getUrlParamWithState: function (key) {
    if (utils.parseUrlParam(key)) return utils.parseUrlParam(key)
    else if (utils.parseUrlParam('state')) {
      try {
        return JSON.parse(utils.base64ToUtf8(utils.getUrlParam('state')))[key]
      } catch (e) {
        return ''
      }
    }
    return ''
  },
  toUrlParam: function (obj) {
    var arr = []
    for (var key in obj) {
      arr.push(key + '=' + encodeURIComponent(obj[key]))
    }
    return arr.join('&')
  },
  toUrlHash: function (obj) {
    var arr = []
    for (var key in obj) {
      arr.push(key + '=' + encodeURIComponent(obj[key]))
    }
    return arr.join('&')
  },
  deleteUrlParam: function (key) {
    var params = utils.getUrlParam()
    if (params[key]) {
      delete params[key]
      window.history.pushState(null, null, location.pathname + '?' + utils.toUrlParam(params))
    }
  },
  updateUrlParam: function (obj) {
    for (var key in obj) utils.deleteUrlParam(key)
    window.history.pushState(null, null, location.href + (/\?/.test(location.href) ? '&' : '?') + utils.toUrlParam(obj))
  },
  setUrlParam: function (obj) {
    var params = utils.getUrlParam()
    for (var key in obj) {
      if (params[key]) {
        var t = {}
        t[key] = obj[key]
        utils.updateUrlParam(t)
      } else {
        var t = {}
        t[key] = obj[key]
        window.history.pushState(null, null, location.href + (/\?/.test(location.href) ? '&' : '?') + utils.toUrlParam(t))
      }
    }
  },
  format: function (x, y) {
    var z = {
      y: x.getFullYear(),
      M: x.getMonth() + 1,
      d: x.getDate(),
      h: x.getHours(),
      m: x.getMinutes(),
      s: x.getSeconds()
    }
    return y.replace(/(y+|M+|d+|h+|m+|s+)/g, function (v) {
      return ((v.length > 1 ? '0' : '') + eval('z.' + v.slice(-1))).slice(-(v.length > 2 ? v.length : 2))
    })
  },
  alert: function (options, yesText) {
    if (typeof options === 'string') {
      // 兼容直接传字符串作为参数的写法
      options = {
        id: Math.ceil(Math.random() * 1000000000),
        message: options,
        yesText: typeof yesText === 'string' ? yesText : '好的',
        yes: utils.noop,
        mask: true
      }
    } else if (typeof options === 'object') {
      options.id = options.id || Math.ceil(Math.random() * 1000000000)
      options.message = options.message || '确定要这么做吗?'
      options.yesText = options.yesText || '好的'
      options.yes = options.yes || function () {}
      options.mask = !options.mask
    } else return

    // 创建提示对话框面板
    var alertMask = document.createElement('div')
    alertMask.setAttribute('id', 'alert-mask-' + options.id)
    alertMask.className = 'alert-mask hidden'
    if (!options.mask) alertMask.style.background = 'transparent'
    alertMask.innerHTML =
      '<div id="alert-box-' + options.id + '" class="alert hidden">' +
      '  <div class="title">' + options.message + '</div>' +
      '  <div id="alert-ok-' + options.id + '" class="button">' + options.yesText + '</div>' +
      '</div>' +
      '<style>' +
      '.alert-mask{position:fixed;top:0;width:100%;height:100%;background:rgba(0,0,0,.8);z-index:1005;overflow:hidden;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-transition:opacity .25s linear 0s;transition:opacity .25s linear 0s}.alert-mask .alert{width:78.667vw;background:#fff;border-radius:2.133vw;text-align:center;-webkit-transition:-webkit-transform .25s linear 0s;transition:-webkit-transform .25s linear 0s;transition:transform .25s linear 0s;transition:transform .25s linear 0s,-webkit-transform .25s linear 0s;content:"viewport-units-buggyfill; width: 78.667vw; border-radius: 2.133vw"}.alert-mask .alert .title{padding:0 5.333vw;min-height:25.6vw;font-size:4.267vw;font-family:VarelaRound-Regular;color:#676c75;line-height:6.4vw;border-bottom:.267vw solid #e7e8ea;content:"viewport-units-buggyfill; padding: 0 5.333vw; min-height: 25.6vw; font-size: 4.267vw; line-height: 6.4vw; border-bottom: 0.267vw solid #e7e8ea"}.alert-mask .alert .button,.alert-mask .alert .title{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.alert-mask .alert .button{min-height:15.2vw;font-size:4.8vw;font-family:PingFangSC-Medium;color:#32cdff;line-height:6.667vw;content:"viewport-units-buggyfill; min-height: 15.2vw; font-size: 4.8vw; line-height: 6.667vw"}.alert-mask .alert.show{-webkit-transform:scale(1);transform:scale(1)}.alert-mask .alert.hidden{-webkit-transform:scale(0);transform:scale(0)}.alert-mask.show{display:-webkit-box;display:-ms-flexbox;display:flex;opacity:1}.alert-mask.hidden{display:none;opacity:0}' +
      '</style>'

    add()

    // 绑定点击事件
    document.getElementById('alert-ok-' + options.id).addEventListener('click', remove, false)

    function add () {
      document.body.appendChild(alertMask)
      document.body.style.overflow = 'hidden'
      alertMask.className = 'alert-mask show'
      setTimeout(function () {
        document.getElementById('alert-box-' + options.id).className = 'alert show'
      }, 0)
    }

    function remove () {
      document.getElementById('alert-box-' + options.id).className = 'alert hidden'
      setTimeout(function () {
        alertMask.className = 'alert-mask hidden'
        document.body.style.overflow = 'auto'
        document.body.removeChild(document.getElementById('alert-mask-' + options.id))
        options.yes(true)
      }, 250)
    }
  },
  utf8ToBase64: function (str) {
    return btoa(unescape(encodeURIComponent(str)))
  },
  base64ToUtf8: function (str) {
    return decodeURIComponent(escape(atob(str)))
  },
  info: function (options, contentText) {
    if (typeof options === 'string') {
      // 兼容直接传字符串作为参数的写法
      options = {
        title: options,
        content: typeof contentText === 'string' ? contentText : ''
      }
    } else if (typeof options === 'object') {
      options.title = options.title || ''
      options.content = options.content || ''
    } else return

    options.id = options.id || Math.ceil(Math.random() * 1000000000)
    options.yes = options.yes || utils.noop
    options.mask = options.mask === undefined ? true : Boolean(options.mask)

    // 创建提示对话框面板
    var infoMask = document.createElement('div')
    infoMask.setAttribute('id', 'info-mask-' + options.id)
    infoMask.className = 'info-mask hidden'
    if (!options.mask) infoMask.style.background = 'transparent'
    infoMask.innerHTML =
      '<div id="info-box-' + options.id + '" class="info hidden">' +
      '  <div class="title">' + options.title + '</div>' +
      '  <div class="content">' + options.content + '</div>' +
      '  <div id="info-close-' + options.id + '" class="close"></div>' +
      '</div>' +
      '<style>' +
      '.info-mask{position:fixed;top:0;width:100%;height:100%;background:rgba(0,0,0,.8);z-index:1004;overflow:hidden;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-transition:opacity .25s linear 0s;transition:opacity .25s linear 0s}.info-mask .info{width:79.733vw;background:#fff;border-radius:2.133vw;text-align:center;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:-webkit-transform .25s linear 0s;transition:-webkit-transform .25s linear 0s;transition:transform .25s linear 0s;transition:transform .25s linear 0s,-webkit-transform .25s linear 0s;padding:6.933vw 7.467vw 8.267vw;color:#333;content:"viewport-units-buggyfill; width: 79.733vw; border-radius: 2.133vw; padding: 6.933vw 7.467vw 8.267vw 7.467vw"}.info-mask .info .title{height:10.4vw;font-size:4.267vw;font-family:PingFangSC-Medium;font-weight:500;content:"viewport-units-buggyfill; height: 10.4vw; font-size: 4.267vw"}.info-mask .info .content{min-height:22.4vw;font-size:3.733vw;font-family:PingFangSC-Regular;font-weight:400;line-height:5.6vw;text-align:left;content:"viewport-units-buggyfill; min-height: 22.4vw; font-size: 3.733vw; line-height: 5.6vw"}.info-mask .info .close{display:inline-block;width:10.133vw;height:10.133vw;margin-left:-5.067vw;position:absolute;bottom:-36.8vw;background:url();background-size:100% 100%;content:"viewport-units-buggyfill; width: 10.133vw; height: 10.133vw; margin-left: -5.067vw; bottom: -36.8vw"}.info-mask .info.show{-webkit-transform:scale(1);transform:scale(1)}.info-mask .info.hidden{-webkit-transform:scale(0);transform:scale(0)}.info-mask.show{display:-webkit-box;display:-ms-flexbox;display:flex;opacity:1}.info-mask.hidden{display:none;opacity:0}' +
      '</style>'

    add()

    // 绑定点击事件
    document.getElementById('info-close-' + options.id).addEventListener('click', remove, false)

    function add () {
      document.body.appendChild(infoMask)
      document.body.style.overflow = 'hidden'
      infoMask.className = 'info-mask show'
      setTimeout(function () {
        document.getElementById('info-box-' + options.id).className = 'info show'
      }, 0)
    }

    function remove () {
      document.getElementById('info-box-' + options.id).className = 'info hidden'
      setTimeout(function () {
        infoMask.className = 'info-mask hidden'
        document.body.style.overflow = 'auto'
        document.body.removeChild(document.getElementById('info-mask-' + options.id))
        options.yes(true)
      }, 250)
    }
  },
  toast: function (options) {
    if (typeof options === 'string') {
      // 兼容直接传字符串作为参数的写法
      options = {
        message: options
      }
    } else if (typeof options === 'object') {
      options.message = options.message || ''
    } else return

    options.id = options.id || Math.ceil(Math.random() * 1000000000)
    options.timer = options.timer || 3000
    options.callback = options.callback || utils.noop
    options.mask = options.mask === undefined ? true : Boolean(options.mask)

    // 创建提示对话框面板
    var toastMask = document.createElement('div')
    toastMask.setAttribute('id', 'toast-mask-' + options.id)
    toastMask.className = 'toast-mask hidden'
    if (!options.mask) toastMask.style.background = 'transparent'
    toastMask.innerHTML =
      '<div id="toast-box-' + options.id + '" class="toast hidden">' + options.message + '</div>' +
      '<style>' +
      '.toast-mask{position:fixed;top:0;bottom:0;left:0;right:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;pointer-events:none;z-index:1004}.toast-mask .toast{min-width:45.333vw;max-width:48.667vw;padding:4vw;line-height:5.333vw;color:#fff;background-color:rgba(0,0,0,.5);border-radius:1.333vw;font-size:3.733vw;text-align:center;display:block;z-index:1009;content:"viewport-units-buggyfill; min-width: 45.333vw; max-width: 48.667vw; padding: 4vw; line-height: 5.333vw; border-radius: 1.333vw; font-size: 3.733vw"}.toast-mask .toast.show{-webkit-transform:scale(1);transform:scale(1)}.toast-mask .toast.hidden{-webkit-transform:scale(0);transform:scale(0)}.toast-mask.show{display:-webkit-box;display:-ms-flexbox;display:flex;opacity:1}.toast-mask.hidden{display:none;opacity:0}' +
      '</style>'

    add()
    setTimeout(remove, options.timer)

    function add () {
      document.body.appendChild(toastMask)
      document.body.style.overflow = 'hidden'
      toastMask.className = 'toast-mask show'
      setTimeout(function () {
        document.getElementById('toast-box-' + options.id).className = 'toast show'
      }, 0)
    }

    function remove () {
      document.getElementById('toast-box-' + options.id).className = 'toast hidden'
      setTimeout(function () {
        toastMask.className = 'toast-mask hidden'
        document.body.style.overflow = 'auto'
        document.body.removeChild(document.getElementById('toast-mask-' + options.id))
        options.callback(true)
      }, 250)
    }
  },
  showLoading: function (text) {
    if (document.getElementById('weui-loading_toast')) return
    var dvMsg = document.createElement('div')
    dvMsg.className = 'weui-loading_toast'
    dvMsg.setAttribute('id', 'weui-loading_toast')
    dvMsg.innerHTML =
      '<div class="weui-mask_transparent"></div>' +
      '<div class="weui-toast">' +
      '    <i class="weui-loading"></i>' +
      '    <p class="weui-toast__content">' + (text || '正在加载') + '</p>' +
      '</div>' +
      '<style>' +
      '.weui-loading_toast .weui-mask_transparent{position:fixed;z-index:1000;top:0;right:0;left:0;bottom:0}.weui-loading_toast .weui-toast{position:fixed;z-index:5000;width:32vw;min-height:32vw;top:48vw;left:50%;margin-left:-16vw;background:hsla(0,0%,7%,.7);text-align:center;border-radius:1.333vw;color:#fff;content:"viewport-units-buggyfill; width: 32vw; min-height: 32vw; top: 48vw; margin-left: -16vw; border-radius: 1.333vw"}.weui-loading_toast .weui-toast .weui-loading{margin:5.867vw auto 2.667vw;width:10.133vw;height:10.133vw;vertical-align:baseline;display:inline-block;-webkit-animation:loading-rotate 1s steps(12) infinite;animation:loading-rotate 1s steps(12) infinite;background:transparent url() no-repeat;background-size:100%;content:"viewport-units-buggyfill; margin: 5.867vw auto 2.667vw auto; width: 10.133vw; height: 10.133vw"}@-webkit-keyframes loading-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes loading-rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.weui-loading_toast .weui-toast .weui-toast__content{margin:0 0 4vw;content:"viewport-units-buggyfill; margin: 0 0 4vw"}' +
      '</style>'
    document.body.appendChild(dvMsg)
  },
  hideLoading: function () {
    document.getElementById('weui-loading_toast') && document.getElementById('weui-loading_toast').parentNode.removeChild(document.getElementById('weui-loading_toast'))
  }
}
for (var util in _utils) window.utils[util] = _utils[util]